using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Cors;
using Microsoft.AspNetCore.DataProtection;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Volo.Abp;
using Volo.Abp.AspNetCore.Mvc;
using Volo.Abp.AspNetCore.Authentication.JwtBearer;
using Volo.Abp.AspNetCore.Serilog;
using Volo.Abp.Autofac;
using Volo.Abp.BackgroundJobs;
using Volo.Abp.BackgroundWorkers;
using Volo.Abp.Caching;
using Volo.Abp.Modularity;
using Volo.Abp.Swashbuckle;
using Volo.Abp.MultiTenancy;
using Volo.Abp.EntityFrameworkCore;
using Volo.Abp.Threading;
using TenantManagementService.HttpApi.Host.HealthChecks;
using TenantManagementService.HttpApi.Middleware;
using TenantManagementService.Monitoring;

namespace TenantManagementService
{
    [DependsOn(
        typeof(AbpAspNetCoreMvcModule),
        typeof(AbpAutofacModule),
        typeof(AbpAspNetCoreAuthenticationJwtBearerModule),
        typeof(AbpAspNetCoreSerilogModule),
        typeof(AbpSwashbuckleModule),
        typeof(AbpEntityFrameworkCoreModule),
        typeof(AbpBackgroundWorkersModule),
        typeof(TenantManagementServiceHttpApiModule),
        typeof(TenantManagementServiceApplicationModule),
        typeof(TenantManagementServiceEntityFrameworkCoreModule)
    )]
    internal class TenantManagementServiceHttpApiHostModule : AbpModule
    {
        public override void ConfigureServices(ServiceConfigurationContext context)
        {
            var configuration = context.Services.GetConfiguration();
            var hostingEnvironment = context.Services.GetHostingEnvironment();

            ConfigureCache(configuration);
            ConfigureDataProtection(context, configuration, hostingEnvironment);
            ConfigureCors(context, configuration);
            ConfigureAuthentication(context, configuration);
            ConfigureSwagger(context, configuration);
            ConfigureHealthChecks(context);
            ConfigurePrometheusMetrics(context, configuration);
        }

        public override void OnApplicationInitialization(ApplicationInitializationContext context)
        {
            var app = context.GetApplicationBuilder();
            var env = context.GetEnvironment();

            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }

            app.UseCorrelationId();
            app.UseStaticFiles();

            // 添加 Prometheus 指标收集中间件（在路由之前）
            app.UseMiddleware<PrometheusMetricsMiddleware>();

            app.UseRouting();
            app.UseCors();
            app.UseAuthentication();

            if (true) // 暂时硬编码多租户启用状态
            {
                app.UseMultiTenancy();
            }

            app.UseAbpRequestLocalization();
            app.UseAuthorization();
            app.UseSwagger();
            app.UseAbpSwaggerUI(c =>
            {
                c.SwaggerEndpoint("/swagger/v1/swagger.json", "TenantManagementService API");
            });

            app.UseAuditing();
            app.UseUnitOfWork();
            app.UseConfiguredEndpoints();

            if (env.IsDevelopment())
            {
                app.UseAbpSerilogEnrichers();
            }
        }

        private void ConfigureCache(IConfiguration configuration)
        {
            Configure<AbpDistributedCacheOptions>(options =>
            {
                options.KeyPrefix = "TenantManagementService:";
            });
        }

        private static void ConfigureDataProtection(
            ServiceConfigurationContext context,
            IConfiguration configuration,
            IWebHostEnvironment hostingEnvironment)
        {
            var dataProtectionBuilder = context.Services.AddDataProtection().SetApplicationName("TenantManagementService");

            if (hostingEnvironment.IsDevelopment())
            {
                dataProtectionBuilder.PersistKeysToFileSystem(new DirectoryInfo(Path.Combine(hostingEnvironment.ContentRootPath, "temp-keys")));
            }
        }

        private static void ConfigureCors(ServiceConfigurationContext context, IConfiguration configuration)
        {
            context.Services.AddCors(options =>
            {
                options.AddDefaultPolicy(builder =>
                {
                    builder
                        .WithOrigins(configuration["App:CorsOrigins"]?
                            .Split(",", StringSplitOptions.RemoveEmptyEntries)
                            .Select(o => o.RemovePostFix("/"))
                            .ToArray() ?? new[] { "*" })
                        .WithAbpExposedHeaders()
                        .SetIsOriginAllowedToAllowWildcardSubdomains()
                        .AllowAnyHeader()
                        .AllowAnyMethod()
                        .AllowCredentials();
                });
            });
        }

//         private void ConfigureAuthentication(ServiceConfigurationContext context, IConfiguration configuration)
//         {
//             var keycloakOptions = configuration.GetSection("Keycloak").Get<KeycloakOptions>() ?? new KeycloakOptions();
// 
//             context.Services.AddAuthentication("Bearer")
//                 .AddJwtBearer(options =>
//                 {
//                     options.Authority = $"{keycloakOptions.ServerUrl}/realms/{keycloakOptions.DefaultRealm}";
//                     options.Audience = keycloakOptions.ClientId ?? "account";
//                     options.RequireHttpsMetadata = keycloakOptions.RequireHttpsMetadata;
//                     options.TokenValidationParameters = new Microsoft.IdentityModel.Tokens.TokenValidationParameters
//                     {
//                         ValidateIssuer = true,
//                         ValidIssuer = $"{keycloakOptions.ServerUrl}/realms/{keycloakOptions.DefaultRealm}",
//                         ValidateAudience = true,
//                         ValidAudience = keycloakOptions.ClientId ?? "account",
//                         ValidateLifetime = true,
//                         ValidateIssuerSigningKey = true
//                     };
//                 });
        // }

        private static void ConfigureAuthentication(ServiceConfigurationContext context, IConfiguration configuration)
        {
            // 临时使用基础JWT认证配置，待Keycloak模块完成后切换到完整的Keycloak集成
            var useKeycloak = configuration.GetValue<bool>("Authentication:UseKeycloak", false);

            if (useKeycloak)
            {
                // TODO: 待Keycloak模块完成后，取消注释以下代码
                /*
                var keycloakOptions = configuration.GetSection("Keycloak").Get<KeycloakOptions>() ?? new KeycloakOptions();

                context.Services.AddAuthentication("Bearer")
                    .AddJwtBearer(options =>
                    {
                        options.Authority = $"{keycloakOptions.ServerUrl}/realms/{keycloakOptions.DefaultRealm}";
                        options.Audience = keycloakOptions.ClientId ?? "account";
                        options.RequireHttpsMetadata = keycloakOptions.RequireHttpsMetadata;
                        options.TokenValidationParameters = new Microsoft.IdentityModel.Tokens.TokenValidationParameters
                        {
                            ValidateIssuer = true,
                            ValidIssuer = $"{keycloakOptions.ServerUrl}/realms/{keycloakOptions.DefaultRealm}",
                            ValidateAudience = true,
                            ValidAudience = keycloakOptions.ClientId ?? "account",
                            ValidateLifetime = true,
                            ValidateIssuerSigningKey = true
                        };
                    });
                */
            }

            // 临时使用基础JWT认证（用于开发和测试）
            context.Services.AddAuthentication("Bearer")
                .AddJwtBearer(options =>
                {
                    // 配置临时认证参数
                    options.Authority = configuration["Authentication:Authority"] ?? "https://localhost:8080/realms/master";
                    options.Audience = configuration["Authentication:Audience"] ?? "account";
                    options.RequireHttpsMetadata = false;
                    options.TokenValidationParameters = new Microsoft.IdentityModel.Tokens.TokenValidationParameters
                    {
                        ValidateIssuer = true,
                        ValidIssuer = configuration["Authentication:Authority"] ?? "https://localhost:8080/realms/master",
                        ValidateAudience = true,
                        ValidAudience = configuration["Authentication:Audience"] ?? "account",
                        ValidateLifetime = true,
                        ValidateIssuerSigningKey = false, // 临时禁用签名验证
                        // 注意：在生产环境中应该启用签名验证
                    };
                });

            // 添加授权服务
            context.Services.AddAuthorization();
        }

        private static void ConfigureSwagger(ServiceConfigurationContext context, IConfiguration configuration)
        {
            context.Services.AddAbpSwaggerGenWithOAuth(
                configuration["AuthServer:Authority"] ?? "https://localhost:44310",
                new Dictionary<string, string>
                {
                    { "TenantManagementService", "租户管理服务 API" }
                },
                options =>
                {
                    options.SwaggerDoc("v1", new Microsoft.OpenApi.Models.OpenApiInfo
                    {
                        Title = "TenantManagementService API",
                        Version = "v1",
                        Description = "Matrix Framework 租户管理服务 RESTful API"
                    });

                    options.DocInclusionPredicate((docName, description) => true);
                    options.CustomSchemaIds(type => type.FullName);
                });
        }

        private static void ConfigureHealthChecks(ServiceConfigurationContext context)
        {
            context.Services.AddHealthChecks()
                .AddCheck<TenantManagementHealthCheck>("tenant-management-service")
                .AddCheck("database", () =>
                {
                    // TODO: 实现实际的数据库连接检查
                    return Microsoft.Extensions.Diagnostics.HealthChecks.HealthCheckResult.Healthy("数据库连接正常");
                })
                .AddCheck("redis", () =>
                {
                    // TODO: 实现实际的Redis连接检查
                    return Microsoft.Extensions.Diagnostics.HealthChecks.HealthCheckResult.Healthy("Redis连接正常");
                })
                .AddCheck("memory", () =>
                {
                    var memoryUsage = GC.GetTotalMemory(false) / 1024 / 1024; // MB
                    if (memoryUsage > 1000) // 超过1GB
                    {
                        return Microsoft.Extensions.Diagnostics.HealthChecks.HealthCheckResult.Degraded($"内存使用较高: {memoryUsage}MB");
                    }
                    return Microsoft.Extensions.Diagnostics.HealthChecks.HealthCheckResult.Healthy($"内存使用正常: {memoryUsage}MB");
                });
        }

        private static void ConfigurePrometheusMetrics(ServiceConfigurationContext context, IConfiguration configuration)
        {
            // 注册 Prometheus 指标服务
            context.Services.AddTransient<PrometheusMetricsService>();

            // 注册后台工作服务
            context.Services.AddBackgroundWorker<AlertRuleEvaluationService>();
            context.Services.AddBackgroundWorker<TenantRenewalService>();

            // 如果需要，可以在这里添加 Prometheus 配置
            var prometheusEnabled = configuration.GetValue<bool>("Prometheus:Enabled", true);
            if (prometheusEnabled)
            {
                context.Services.Configure<PrometheusOptions>(options =>
                {
                    options.Enabled = true;
                    options.MetricsPath = configuration.GetValue<string>("Prometheus:MetricsPath", "/metrics");
                    options.IncludeDefaults = configuration.GetValue<bool>("Prometheus:IncludeDefaults", true);
                });
            }
        }
    }

    /// <summary>
    /// Prometheus 配置选项
    /// </summary>
    public class PrometheusOptions
    {
        public bool Enabled { get; set; } = true;
        public string MetricsPath { get; set; } = "/metrics";
        public bool IncludeDefaults { get; set; } = true;
    }
}